//  Copyright (c) 2012 M.A. (Thijs) van den Berg, http://sitmo.com/
//
//  Use, modification and distribution are subject to the MIT Software License. 
// (See accompanying file LICENSE.txt or copy at http://www.stdfin.org/LICENSE.txt)

#define BOOST_TEST_MODULE stdfin_threefry
#include <boost/test/included/unit_test.hpp>
#include <stdfin/random/threefry_engine.hpp>

BOOST_AUTO_TEST_SUITE(random_threefry_engine)

BOOST_AUTO_TEST_CASE( threefry_engine_discard )
{
    stdfin::threefry_engine a,b;
    for (int i=0; i<3; ++i) a(); b.discard(3);
    BOOST_CHECK_EQUAL( a(), b() );

    for (int i=0; i<8; ++i) a(); b.discard(8);
    BOOST_CHECK_EQUAL( a(), b() );

    for (int i=0; i<11; ++i) a(); b.discard(11);
    BOOST_CHECK_EQUAL( a(), b() );

    for (int i=0; i<123; ++i) a(); b.discard(123);
    BOOST_CHECK_EQUAL( a(), b() );

}

BOOST_AUTO_TEST_CASE( threefry_engine_copy_constructor ) 
{
    stdfin::threefry_engine a; a(); a(); a();
    stdfin::threefry_engine b(a);
    BOOST_CHECK_EQUAL( a(), b() );
}

BOOST_AUTO_TEST_CASE( threefry_engine_copy_io_stream ) 
{
    stdfin::threefry_engine a; a(); a(); a();
    stdfin::threefry_engine b;
    std::stringstream s;
    s << a;
    s >> b;
    BOOST_CHECK_EQUAL( a(), b() );
}

BOOST_AUTO_TEST_CASE( threefry_engine_numbers )
{
    stdfin::threefry_engine eng;
    
    // test 1:
    BOOST_CHECK_EQUAL( eng() , 0xe6c85537 );
    BOOST_CHECK_EQUAL( eng() , 0x09218ebd );
    BOOST_CHECK_EQUAL( eng() , 0x66d86105 );
    BOOST_CHECK_EQUAL( eng() , 0x55941f52 );
    BOOST_CHECK_EQUAL( eng() , 0x282434dc );
    BOOST_CHECK_EQUAL( eng() , 0x4bd25e16 );
    BOOST_CHECK_EQUAL( eng() , 0x6bd2e40b );
    BOOST_CHECK_EQUAL( eng() , 0xee29ec84 );

    // test 2:
    eng.set_counter(0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff);
    eng.set_key(    0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff);
    
    BOOST_CHECK_EQUAL( eng() , 0x942bba1b );
    BOOST_CHECK_EQUAL( eng() , 0x29c24097 );
    BOOST_CHECK_EQUAL( eng() , 0x0f6f4e11 );
    BOOST_CHECK_EQUAL( eng() , 0x0371bbfb );
    BOOST_CHECK_EQUAL( eng() , 0x33f83a1c );
    BOOST_CHECK_EQUAL( eng() , 0x3c231ffa );
    BOOST_CHECK_EQUAL( eng() , 0xde32d168 );
    assert( eng() == 0xcd29113f );

    // test 3:
    eng.set_counter(0x243f6a8885a308d3, 0x13198a2e03707344, 0xa4093822299f31d0, 0x082efa98ec4e6c89);
    eng.set_key(    0x452821e638d01377, 0xbe5466cf34e90c6c, 0xbe5466cf34e90c6c, 0xc0ac29b7c97c50dd);
    
    BOOST_CHECK_EQUAL( eng() , 0x91651bd9 );
    BOOST_CHECK_EQUAL( eng() , 0xa7e8fde5 );
    BOOST_CHECK_EQUAL( eng() , 0x0138319b );
    BOOST_CHECK_EQUAL( eng() , 0xbaafd0c3 );
    BOOST_CHECK_EQUAL( eng() , 0x29e685b9 );
    BOOST_CHECK_EQUAL( eng() , 0x84a5c1a7 );
    BOOST_CHECK_EQUAL( eng() , 0xcebc1ba4 );
    BOOST_CHECK_EQUAL( eng() , 0x901d406c );
}

BOOST_AUTO_TEST_SUITE_END()
